Previous: Accumulation Clauses, Up: Loop Facility [Contents][Index]
This section describes the remaining loop clauses.
with var = valueThis clause binds a variable to a value around the loop, but otherwise leaves the variable alone during the loop. The following loops are basically equivalent:
(cl-loop with x = 17 do …) (let ((x 17)) (cl-loop do …)) (cl-loop for x = 17 then x do …)
Naturally, the variable var might be used for some purpose in the rest of the loop. For example:
(cl-loop for x in my-list with res = nil do (push x res)
finally return res)
This loop inserts the elements of my-list at
the front of a new list being accumulated in
res, then returns the list res at
the end of the loop. The effect is similar to that of a
collect clause, but the list gets reversed by
virtue of the fact that elements are being pushed onto the
front of res rather than the end.
If you omit the = term, the variable is
initialized to nil. (Thus the ‘=
nil’ in the above example is unnecessary.)
Bindings made by with are sequential by
default, as if by let*. Just like
for clauses, with clauses can be
linked with and to cause the bindings to be made
by let instead.
if condition clauseThis clause executes the following loop clause only if the
specified condition is true. The following clause
should be an accumulation, do,
return, if, or unless
clause. Several clauses may be linked by separating them with
and. These clauses may be followed by
else and a clause or clauses to execute if the
condition was false. The whole construct may optionally be
followed by the word end (which may be used to
disambiguate an else or and in a
nested if).
The actual non-nil value of the condition
form is available by the name it in the
“then” part. For example:
(setq funny-numbers '(6 13 -1))
⇒ (6 13 -1)
(cl-loop for x below 10
if (cl-oddp x)
collect x into odds
and if (memq x funny-numbers) return (cdr it) end
else
collect x into evens
finally return (vector odds evens))
⇒ [(1 3 5 7 9) (0 2 4 6 8)]
(setq funny-numbers '(6 7 13 -1))
⇒ (6 7 13 -1)
(cl-loop <same thing again>)
⇒ (13 -1)
Note the use of and to put two clauses into
the “then” part, one of which is itself an
if clause. Note also that end,
while normally optional, was necessary here to make it clear
that the else refers to the outermost
if clause. In the first case, the loop returns a
vector of lists of the odd and even values of x.
In the second case, the odd number 7 is one of the
funny-numbers so the loop returns early; the
actual returned value is based on the result of the
memq call.
when condition
clauseThis clause is just a synonym for if.
unless condition
clauseThe unless clause is just like
if except that the sense of the condition is
reversed.
named nameThis clause gives a name other than nil to
the implicit block surrounding the loop. The name
is the symbol to be used as the block name.
initially [do] forms…This keyword introduces one or more Lisp forms which will
be executed before the loop itself begins (but after any
variables requested by for or with
have been bound to their initial values).
initially clauses can appear anywhere; if there
are several, they are executed in the order they appear in
the loop. The keyword do is optional.
finally [do] forms…This introduces Lisp forms which will be executed after
the loop finishes (say, on request of a for or
while). initially and
finally clauses may appear anywhere in the loop
construct, but they are executed (in the specified order) at
the beginning or end, respectively, of the loop.
finally return formThis says that form should be executed after
the loop is done to obtain a return value. (Without this, or
some other clause like collect or
return, the loop will simply return
nil.) Variables bound by for,
with, or into will still contain
their final values when form is executed.
do forms…The word do may be followed by any number of
Lisp expressions which are executed as an implicit
progn in the body of the loop. Many of the
examples in this section illustrate the use of
do.
return formThis clause causes the loop to return immediately. The
following Lisp form is evaluated to give the return value of
the loop form. The finally clauses, if any, are
not executed. Of course, return is generally
used inside an if or unless, as its
use in a top-level loop clause would mean the loop would
never get to “loop” more than once.
The clause ‘return
form’ is equivalent to
‘do (cl-return form)’ (or
cl-return-from if the loop was named). The
return clause is implemented a bit more
efficiently, though.
While there is no high-level way to add user extensions to
cl-loop, this package does offer two properties
called cl-loop-handler and
cl-loop-for-handler which are functions to be called
when a given symbol is encountered as a top-level loop clause or
for clause, respectively. Consult the source code in
file cl-macs.el for details.
This package’s cl-loop macro is compatible
with that of Common Lisp, except that a few features are not
implemented: loop-finish and data-type specifiers.
Naturally, the for clauses that iterate over
keymaps, overlays, intervals, frames, windows, and buffers are
Emacs-specific extensions.
Previous: Accumulation Clauses, Up: Loop Facility [Contents][Index]